home *** CD-ROM | disk | FTP | other *** search
/ MACD 5 / MACD 5.bin / workbench / libs / unixlib.lha / unix / test / exec_test3.c < prev    next >
C/C++ Source or Header  |  1996-07-07  |  3KB  |  136 lines

  1. /* test program for exec() in unix.lib
  2.  *
  3.  * Launches as a child a program specified on the command line. The child
  4.  * must perform input and output from its standard I/O. Precisely it must
  5.  * request something in input and produce output conseguently.
  6.  * The program: 1) attaches the write end of a pipe to the standard output of
  7.  * the child and reads its output from the read end; 2) attaches the read
  8.  * end of another pipe to the standard input of the child and passes input
  9.  * to it from the write end.
  10.  */
  11.  
  12. #include <stdio.h>
  13. #include <errno.h>
  14. #include <stdlib.h>
  15. #include <unistd.h>
  16. #include <signal.h>
  17. #include <sys/wait.h>
  18. #include <dos/dos.h>
  19. #include <proto/dos.h>
  20.  
  21. typedef unsigned char bool;
  22.  
  23. #define FALSE 0
  24. #define TRUE  1
  25.  
  26. char *program;
  27.  
  28. void
  29. LogFatal(char *x0, char *x1)
  30. {
  31.     extern char *sys_errlist[];
  32.     static bool entered = FALSE;
  33.  
  34.     if (entered)
  35.         return;
  36.     entered = TRUE;
  37.  
  38.     fprintf(stderr, "%s: ", program);
  39.     if (errno)
  40.         fprintf(stderr, "%s: ", sys_errlist[ errno ]);
  41.     fprintf(stderr, x0,x1);
  42.     fprintf(stderr, "  Stop.\n");
  43.     exit(20);
  44. }
  45.  
  46. void
  47. LogFatalI(char *s, int i)
  48. {
  49.     /*NOSTRICT*/
  50.     LogFatal(s, (char *)i);
  51. }
  52.  
  53. int fd;
  54.  
  55. void
  56. sendc(int sig)
  57. {                /* if the child doesn't output the wanted */
  58.     write(fd, ">", 1);    /* char '>' within the amount of time     */
  59.     close(fd);        /* specified in alarm(), we do it for him */
  60. }                /* so as to non block the parent          */
  61.  
  62. int
  63. main(int ac, char **av)
  64. {
  65.     int  pid, status;
  66.     int  std_in[2];
  67.     int  std_out[2];
  68.     int  c;
  69.     char *comm;
  70.     char *argv[3];
  71.     FILE *infp;
  72.     FILE *outfp;
  73.  
  74.     if (ac == 1 || ac > 3) {
  75.         fprintf(stderr, "Usage: %s test-program [argument]\n", av[0]);
  76.         exit(EXIT_FAILURE);
  77.     }
  78.  
  79.     program = av[0];
  80.     comm = av[1];
  81.     argv[0] = av[1];
  82.     if (ac == 3)
  83.         argv[1] = av[2];
  84.     else
  85.         argv[1] = NULL;
  86.     argv[2] = NULL;
  87.  
  88.     /* The exec() function in unix.lib starts a child process. */
  89.     /* It is possible to give the child input, output, current */
  90.     /* dir and stack different from the parent. If the input   */
  91.     /* or the output of the child are changed, they are closed */
  92.     /* after the child exits. Exec() returns the child pid.    */
  93.  
  94.     if (pipe(std_in) != 0 || pipe(std_out) != 0)
  95.         LogFatal("Cannot get a pipe.", "");
  96.  
  97.     if (!(infp = fdopen(std_out[0], "r")) ||
  98.         !(outfp = fdopen(std_in[1], "w")))
  99.         LogFatal("Cannot attach a stream to pipe.", "");
  100.  
  101.     /* fd is used in sendc() to provide the '>' char */
  102.     fd = dup(std_out[1]);
  103.     pid = exec(comm, argv, std_in[0], std_out[1], NULL, 4096);
  104.     if (pid < 0)
  105.         LogFatal("Cannot exec %s.", comm);
  106.  
  107.     printf("child request: ");
  108.     signal(SIGALRM, sendc);
  109.     alarm(2);
  110.     while((c = getc(infp)) != '>')
  111.         putchar(c);
  112.     alarm(0);
  113.     fflush(stdout);
  114.     
  115.     while((c = getchar()) != '\n')
  116.         putc(c, outfp);
  117.     putc('\n', outfp);
  118.     fclose(outfp);
  119.  
  120.     printf("child response: ");
  121.     while((c = getc(infp)) != '\n')
  122.         putchar(c);
  123.     putchar('\n');
  124.     fclose(infp);
  125.  
  126.     /* Simply wait child completion */
  127.     if (wait(&status) > 0) {
  128.         if (WIFSIGNALED(status))
  129.             LogFatalI("Signal %d.", WTERMSIG(status));
  130.         if (WIFEXITED(status) && WEXITSTATUS(status))
  131.             LogFatalI("Exit code %d.", WEXITSTATUS(status));
  132.     }
  133.  
  134.     return(WEXITSTATUS(status));
  135. }
  136.